/**
 * 20220119：finalized by jordia
 */
import BroadPhase from "./broad-phase";
import PhysicsProxy from "./physics-proxy";
import GjkEpa from "../collision-detector/gjk-epa-detector/gjk-epa";
import CONSTANT from '../constant';
import Method from "../common/method";

/**
 * 遍历粗测
 */
export default class BruteForceBroadPhase extends BroadPhase{
    constructor() {
        super(CONSTANT.BROAD_PHASE_TYPE_BRUTE_FORCE);
        this._incremental = false;
    }
    createProxy(userData,aabb) {
        let proxy = new PhysicsProxy(userData,this._idCount++);
        this._numProxies=this._setProxyList(this._numProxies,proxy,aabb);
        return proxy;
    }
    destroyProxy(proxy) {
        this._numProxies--;
        let prev = proxy._prev;
        let next = proxy._next;
        if(prev != null) {
            prev._next = next;
        }
        if(next != null) {
            next._prev = prev;
        }
        if(proxy === this._proxyList) {
            this._proxyList = this._proxyList._next;
        }
        if(proxy === this._proxyListLast) {
            this._proxyListLast = this._proxyListLast._prev;
        }
        proxy._next = null;
        proxy._prev = null;
        proxy.userData = null;
    }
    moveProxy(proxy,aabb,displacement) {
        Method.copyElements(aabb.elements,proxy.size,0,0,6);
    }
    collectPairs() {
        let p = this._proxyPairList;
        if(p != null) {
            while(true) {
                p._p1 = null;
                p._p2 = null;
                p = p._next;
                if(!(p != null)) break;
            }
            this._proxyPairList._next = this._proxyPairPool;
            this._proxyPairPool = this._proxyPairList;
            this._proxyPairList = null;
        }
        this._testCount = 0;
        let p1 = this._proxyList;
        while(p1 != null) {
            let n = p1._next, p2 = p1._next;
            while(p2 != null) {
                let n = p2._next;
                this._testCount++;
                if(Method.boxIntersectsBox(p1.size,p2.size)) {
                    let pp=this._setProxyPairList();
                    pp._p1 = p1;
                    pp._p2 = p2;
                }
                p2 = n;
            }
            p1 = n;
        }
    }
    rayCast(begin,end,callback) {
        let p1e=begin.elements, p2e=end.elements;
        let p = this._proxyList;
        while(p != null) {
            let n = p._next;
            let pe=p.size;
            let tmp=this._raycastTest(pe,p1e[0],p1e[1],p1e[2],p2e[0],p2e[1],p2e[2]);
            if(tmp) {
                callback.process(p);
            }
            p = n;
        }
    }
    convexCast(convex,begin,translation,callback) {
        let p = this._proxyList;
        while(p != null) {
            let n = p._next;
            let abi=this._aabb.min.elements,aba=this._aabb.max.elements,pe=p.size;
            Method.copyElements(pe,abi,0,0,3);
            Method.copyElements(pe,aba,3,0,3);
            this._convexSweep.init(convex,begin,translation);
            let gjkEpa = GjkEpa.instance;
            if(gjkEpa.computeClosestPointsImpl(this._convexSweep,this._aabb,begin,this.identity,null,false) === 0 && gjkEpa.distance <= 0) {
                callback.process(p);
            }
            p = n;
        }
    }
    aabbTest(aabb,callback) {
        let p = this._proxyList, ae=aabb.elements;
        while(p != null) {
            let n = p._next;
            if(Method.boxIntersectsBox(ae,p.size)) {
                callback.process(p);
            }
            p = n;
        }
    }
}